package com.ku.kill.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.druid.support.json.JSONUtils;
import com.ku.kill.dao.UserDOMapper;
import com.ku.kill.dao.UserPasswordDOMapper;
import com.ku.kill.dataobject.UserDO;
import com.ku.kill.dataobject.UserPasswordDO;
import com.ku.kill.error.BusinessException;
import com.ku.kill.error.EmBusinessError;
import com.ku.kill.service.UserService;
import com.ku.kill.service.model.UserModel;
import com.ku.kill.validator.ValidationResult;
import com.ku.kill.validator.ValidatorImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.TimeUnit;

/**
 * @program: kill2
 * @description:
 * @author: JokerKu
 * @create: 2020-04-02 15:24
 **/
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDOMapper userDOMapper;
    @Autowired
    private UserPasswordDOMapper userPasswordDOMapper;
    @Autowired
    private ValidatorImpl validator;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public UserModel getUserById(Integer id) throws BusinessException {
        try {
            UserDO userDO = userDOMapper.selectByPrimaryKey(id);
            if (userDO == null) {
                return null;
            }
            //通过用户Id获取用户加密密码信息
            UserPasswordDO userPasswordDO = userPasswordDOMapper.selectByUserId(userDO.getId());
            return convertFromDataObject(userDO, userPasswordDO);
        } catch (Exception e) {
            throw new BusinessException(EmBusinessError.PARMATER_VALIDATION_ERROR, "查询失败！");
        }
    }

    //用户注册
    @Transactional
    @Override
    public void register(UserModel userModel) throws BusinessException {

        if (userModel == null) {
            throw new BusinessException(EmBusinessError.PARMATER_VALIDATION_ERROR);
        }
//        if (StrUtil.isEmpty(userModel.getName())
//                || userModel.getAge() == null
//                || userModel.getGender() == null
//                || StrUtil.isEmpty(userModel.getTelphone())
//                || StrUtil.isEmpty(userModel.getEncrptPasswprd())) {
//            throw new BusinessException(EmBusinessError.PARMATER_VALIDATION_ERROR);
//        }
        ValidationResult validateRe = validator.validate(userModel);
        if (validateRe.isHasErrors()){
            throw new BusinessException(EmBusinessError.PARMATER_VALIDATION_ERROR,validateRe.getErrMsg());
        }

        try {
            //model-->dataObject
            UserDO userDO = convertFromUserModel(userModel);
            //insertSelective的sql语句上使用属性：keyProperty="id" useGeneratedKeys="true"开启后插入数据的id会直接赋值到领域模型的实体id中
            userDOMapper.insertSelective(userDO);
            userModel.setId(userDO.getId());
            UserPasswordDO userPasswordDO = convertPwdFromUserModel(userModel);
            userPasswordDOMapper.insertSelective(userPasswordDO);
        } catch (DuplicateKeyException e) {
            //telphone上加了唯一索引，如果手机号已被注册，那么会报DuplicateKeyException错误
            throw new BusinessException(EmBusinessError.PARMATER_VALIDATION_ERROR, "手机号已被注册！");
        }

    }

    //用户登录
    @Override
    public UserModel validateLogin(String encrptPassword, String telphone) throws BusinessException {
        //通过用户手机号查询用户信息
        UserDO userDO = userDOMapper.selectBytelphone(telphone);
        if (userDO == null) {
            throw new BusinessException(EmBusinessError.USER_LOGIN_FAIL);
        }
        UserPasswordDO userPasswordDO = userPasswordDOMapper.selectByUserId(userDO.getId());
        if (userPasswordDO == null) {
            throw new BusinessException(EmBusinessError.USER_LOGIN_FAIL);
        }
        //对比密码是否相同 密码为空或密码不相等直接抛出异常
        if (!(StrUtil.isNotBlank(userPasswordDO.getEncrptPassword())
                && StrUtil.equals(userPasswordDO.getEncrptPassword(), encrptPassword))) {
            throw new BusinessException(EmBusinessError.USER_LOGIN_FAIL);
        }
        //最终如果没有抛出异常，那么表示登录成功，返回用户信息
        return convertFromDataObject(userDO, userPasswordDO);
    }

    @Override
    public UserModel getUserByIdInCache(Integer id) throws BusinessException {
        String userStr = redisTemplate.opsForValue().get("USER_VALIDATE:" + id);
        UserModel userModel = null;
        //为空，数据库取
        if (StrUtil.isEmpty(userStr)){
             userModel = this.getUserById(id);
             if (userModel == null){
                 return null;
             }
             redisTemplate.opsForValue().set("USER_VALIDATE:" + id, JSONUtil.toJsonStr(userModel),10, TimeUnit.MINUTES);
             return userModel;
        }
        //不为空
        userModel = JSONUtil.toBean(userStr,UserModel.class);
        System.out.println("user走缓存");
        return userModel;
    }

    //model-->dataObject
    private UserPasswordDO convertPwdFromUserModel(UserModel userModel) {
        if (userModel == null) {
            return null;
        }
        UserPasswordDO userPasswordDO = new UserPasswordDO();
        BeanUtil.copyProperties(userModel, userPasswordDO);
        userPasswordDO.setUserId(userModel.getId());
        userPasswordDO.setEncrptPassword(userModel.getEncrptPasswprd());
        log.warn(userPasswordDO.toString());
        return userPasswordDO;
    }

    //model-->dataObject
    private UserDO convertFromUserModel(UserModel userModel) {
        if (userModel == null) {
            return null;
        }
        UserDO userDO = new UserDO();
        BeanUtil.copyProperties(userModel, userDO);
        return userDO;
    }

    //dataObject-->model
    private UserModel convertFromDataObject(UserDO userDO, UserPasswordDO userPasswordDO) {
        if (userDO == null) {
            return null;
        }
        UserModel userModel = new UserModel();
        BeanUtil.copyProperties(userDO, userModel);
        if (userPasswordDO != null) {
            userModel.setEncrptPasswprd(userPasswordDO.getEncrptPassword());
        }
        return userModel;
    }
}
